从2167到6079TPS的一次vLLM 950单卡压测

前言

最近在 Ascend 950PR 上部署 Qwen3.5-4B,最开始直连 vLLM 压测只有:

1
2
Total TPS:  2167.47 tok/s
Output TPS: 426.57 tok/s

设备利用率偶尔能到 100%,但全程平均只有 26.2%,HBM 也只用了约 40%。显然当前配置没有把服务喂满。

后来在 --enforce-eager 下,最高稳定结果做到:

1
2
Total TPS:  6078.81 tok/s
Output TPS: 1196.22 tok/s

大约是最初的 2.8 倍

TPS

vllm bench serve 同时给出 Total token throughput 和 Output token throughput。

Total TPS = (input token + output token) / time
Output TPS = output token / time

调大batch时撞上了72GiB OOM

max-num-batched-tokens 从 8192 提到 16384 后,vLLM 在启动 profile 阶段直接报:

1
NPU out of memory. Tried to allocate 72.00 GiB

16k 上下文显然不应该平白消耗 72 GiB,这个数字明显是有问题的

沿堆栈追到 LoRA 的 PyTorch fallback 后发现,问题出在高级索引:

1
2
3
selected_loras = lora_b_weights[lora_indices_tensor].to(
dtype=output_tensor.dtype
)

当时的形状为:

1
2
3
max_num_batched_tokens = 16384
max_lora_rank = 128
intermediate_size = 9216

代码把 LoRA-A 权重按每个 token 展开成:

1
[16384, 1, 128, 9216]

元素总数:

1
2
16384 × 1 × 128 × 9216
= 19,327,352,832

高级索引先产生一份 BF16 临时张量:

1
19,327,352,832 × 2 bytes = 36 GiB

随后 .to(float32) 又要申请:

1
19,327,352,832 × 4 bytes = 72 GiB

日志里的 72 GiB 正好对上。

正常 grouped SGMV 不应该给每个 token 复制整份 [128,9216] 权重。它真正需要的 LoRA-A 只有约 2.25 MiB/slot,输出 buffer 也只有约 8 MiB。

所以这不是 16k 上下文的正常显存需求,也不是 KV Cache 太大,而是 rank-128 触发的 fallback 实现把权重按 token 展开了。

他给每个位置的token都复制了一份lora weight, 真是垃圾的实现

暂时关闭LoRA,单独测base model上限

这轮目标是测 base model 吞吐,不需要让 LoRA profile 干扰结果,因此先临时关闭 LoRA,把 batch token 提到能覆盖输入的范围,再扫描客户端并发。

服务端仍限制 32 active seq 时:

客户端并发 Total TPS Output TPS 现象
16 2439.85 480.17 尚未饱和
32 2915.96 573.88 明显提升
64 4092.61 805.44 排队请求减少调度空洞
128 4218.27 830.10 接近平台
256 4265.51 839.39 只再提升约1.1%

这里有个很实用的现象:客户端并发高于服务端 active seq 并不一定没用。多一些排队请求可以让完成的 sequence 立刻被新请求补上,提高持续利用率,代价是 TTFT 变大。

继续提高服务端active seq

关闭 LoRA 后 KV Cache 有足够余量,于是继续按比例增加:

active seq max batched tokens 客户端并发 Total TPS Output TPS
32 16384 256 4265.51 839.39
64 32768 256 5617.57 1105.46
128 65536 256 6078.81 1196.22

最高稳定档的完整数据:

1
2
3
4
5
6
7
8
Successful requests:       256
Failed requests: 0
Benchmark duration: 27.39 s
Request throughput: 9.35 req/s
Total token throughput: 6078.81 tok/s
Output token throughput:1196.22 tok/s
Mean TTFT: 15952.14 ms
Mean TPOT: 43.38 ms

对应设备状态:

1
2
3
平均利用率:45.6%
最大利用率:100%
最大HBM:约87.4%

吞吐提高了,但 TTFT 也到了约 16 秒。批处理越大,硬件效率通常越高,请求排队也越久。

为什么没有继续堆到256

我也试了更大的服务端 batch:

1
256 active seq / 131072 tokens

启动 profile 触发 Ascend 算子限制:

1
coreDim=65536,要求 <=65535

只能说 Ascend 和 vllm 之间的适配还需要时间, 测试过程问题很多

作者

Noah Shen

发布于

2026-07-21

更新于

2026-07-21

许可协议

评论